﻿namespace ImapComponent.Net.Mail.Imap4
{
    using System;
    using System.Collections.Generic;

    /// <summary>
    /// Represents the number message collection.
    /// </summary>
    public abstract class MessageNumberCollection : List<int>
    {
        #region Methods

        /// <summary>
        /// Adds a new message number to the list if it does not already contain it.
        /// </summary>
        /// <param name="value">A new value to be added.</param>
        public new void Add(int value)
        {
            if (!Contains(value))
            {
                base.Add(value);
            }
        }

        /// <summary>
        /// Adds a range of message numbers to the list.
        /// </summary>
        /// <param name="valueRange">A value range to be added represented by a string.</param>
        public void AddRange(string valueRange)
        {
            int start = Int32.Parse(valueRange.Split(':')[0]);
            int end = Int32.Parse(valueRange.Split(':')[1]);

            for (int index = start; index <= end; index++)
            {
                this.Add(index);
            }
        }

        /// <summary>
        /// Joins the message number collection with another message number collection.
        /// </summary>
        /// <param name="valueSet">A message number collection to be joined.</param>
        public void AddSet(MessageNumberCollection valueSet)
        {
            foreach (int value in valueSet)
            {
                this.Add(value);
            }
        }

        /// <summary>
        /// Removes a range of message numbers from the list.
        /// </summary>
        /// <param name="valueRange">A value range to be removed represented by a string.</param>
        public void RemoveRange(string valueRange)
        {
            int start = Int32.Parse(valueRange.Split(':')[0]);
            int end = Int32.Parse(valueRange.Split(':')[1]);

            for (int index = start; index <= end; index++)
            {
                base.Remove(index);
            }
        }

        /// <summary>
        /// Removes all message numbers of the specified message number collection from the collection.
        /// </summary>
        /// <param name="valueSet">A message number collection to be removed.</param>
        public void RemoveSet(MessageNumberCollection valueSet)
        {
            foreach (int value in valueSet)
            {
                base.Remove(value);
            }
        }

        /// <summary>
        /// Concatenates the message number collection to a string.
        /// </summary>
        /// <returns>The message number collection in string format.</returns>
        public override string ToString()
        {
            if (this.Count == 0)
            {
                return string.Empty;
            }
            else if (this.Count == 1)
            {
                return this[0].ToString();
            }
            else 
            {
                this.Sort();
                List<string> resultList = new List<string>();
                int start = this[0];
                int end = this[0];

                for (int index = 1; index < this.Count; index++)
                {
                    if (this[index] - 1 == end)
                    {
                        end = this[index];
                    }
                    else 
                    {
                        if (start == end)
                        {
                            resultList.Add(start.ToString());
                        }
                        else 
                        {
                            resultList.Add(start.ToString() + ":" + end.ToString());
                        }

                        start = this[index];
                        end = this[index];
                    }
                }

                if (start == end)
                {
                    resultList.Add(start.ToString());
                }
                else
                {
                    resultList.Add(start.ToString() + ":" + end.ToString());
                }

                return string.Join(",", resultList.ToArray());
            }
        }

        #endregion // Methods
    }
}
